package com.huawei.experiencereuse;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Base64;
import java.net.URI;
import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
//import java.net.http.HttpClient;
//import java.net.http.HttpRequest;
//import java.net.http.HttpResponse;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;


public class ImageSemanticAnalyzer {
    private static final String TAG = "ImageSemanticAnalyzer";
    public static final String API_KEY = "sk-zkmbywtoxsuoeuyrcaiwvwkaevqcbplxnljkcahcordqxnwk";
    public static final String API_URL = "https://api.siliconflow.cn/v1/chat/completions";
    public static final String MODEL_NAME = "Pro/Qwen/Qwen2.5-VL-7B-Instruct";
//    public static final String API_KEY = "ollama";
//    public static final String API_URL = "http://10.123.183.18:11434/v1/chat/completions";
//    public static final String MODEL_NAME = "qwen2.5vl:7b";

    private final SiliconFlowClient client;
    private final ObjectMapper objectMapper;
    private Context context;
    public ImageSemanticAnalyzer(Context context) {
        this.client = new SiliconFlowClient();
        this.objectMapper = new ObjectMapper();
        this.context = context;
    }

    /**
     * Compare the semantic meaning of image1 with the description
     * @param image1Str Primary comparison image
     * @param image2Str Reference image (not used in current version)
     * @param desc Description text
     */
    public void compareImageWithDescription(String image1Str, String image2Str, String desc,
                                            ImageSemanticAnalyzerCallback callback) {
        try {
            Path image1 = Paths.get(image1Str);
            System.out.println("[DEBUG] Starting image analysis...");
            System.out.println("[DEBUG] Image file size: " + Files.size(image1) + " bytes");

            String image1Base64 = encodeImageToBase64(image1);
            System.out.println("[DEBUG] Image encoded to Base64, length: " + image1Base64.length() + " chars");

            String image2Base64 = encodeAssetImageToBase64(image2Str);
            System.out.println("[DEBUG] Image encoded to Base64, length: " + image2Base64.length() + " chars");

            String prompt = buildComparisonPrompt(desc);
            System.out.println("[DEBUG] Prompt: " + prompt);

            System.out.println("[DEBUG] Sending request to SiliconFlow API...");
            new Thread(()->{
                try {
                    String response = client.sendRequest(image1Base64, image2Base64, prompt);
                    System.out.println("[DEBUG] API Response received: " + response);

                    boolean result = parseResponse(response);
                    System.out.println("[DEBUG] Parsed result: " + result);

                    callback.onSuccess(result);

                } catch (Exception e) {
                    // 切换到主线程回调错误信息
                    String errorMsg = "比较失败：" + e.getMessage();
                    Log.e(TAG, errorMsg, e);
                    callback.onError(new Exception(errorMsg));
                }
            }).start();

        } catch (Exception e) {
            System.err.println("[ERROR] Analysis failed: " + e.getMessage());
        }
    }

    private String encodeImageToBase64(Path imagePath) throws IOException {
        byte[] imageBytes = Files.readAllBytes(imagePath);
        String base64 = Base64.getEncoder().encodeToString(imageBytes);
        System.out.println("[DEBUG] Successfully encoded image: " + imagePath.getFileName());
        return base64;
    }

    private String encodeAssetImageToBase64(String imagePath) throws IOException {
        // 1. 获取AssetManager实例
        InputStream inputStream = this.context.getAssets().open(imagePath);

        // 2. 将输入流转换为字节数组
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024*1024]; // 缓冲区
        int bytesRead;
        // 循环读取输入流到缓冲区，再写入输出流
        while ((bytesRead = inputStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, bytesRead);
        }
        outputStream.flush(); // 确保所有数据写入

        // 3. 返回字节数组（与Files.readAllBytes()结果一致）
        String base64 = Base64.getEncoder().encodeToString(outputStream.toByteArray());
        System.out.println("[DEBUG] Successfully encoded image: " + imagePath);
        return base64;
    }

    private String buildComparisonPrompt(String description) {
        // return "Analyze the image and compare it with the provided description. If the overall outlines match, return only true. If they do not match, return false followed by an explanation of the discrepancy in chinese. The provided description is:"+ description;
        return "The two images are screenshots of app operations. Please analyze each screenshot separately, understand their overall outlines content, and then compare whether they represent the same state after app operations. Please note that information such as advertisements can be ignored. If the overall outlines match, return only true. If they do not match, return false followed by an explanation of the discrepancy in chinese.";
    }

    private boolean parseResponse(String response) {
        try {
            System.out.println("[DEBUG] Parsing API response...");
            ObjectNode jsonResponse = objectMapper.readValue(response, ObjectNode.class);
            System.out.println("[DEBUG] Full JSON response: " + jsonResponse.toPrettyString());
            String content = jsonResponse.path("choices")
                    .get(0)
                    .path("message")
                    .path("content")
                    .asText()
                    .trim()
                    .toLowerCase();

            System.out.println("[DEBUG] Extracted content: \"" + content + "\"");
            boolean result = "true".equals(content);
            System.out.println("[DEBUG] Final boolean result: " + result);
            return result;
        } catch (Exception e) {
            System.err.println("[ERROR] Failed to parse response: " + e.getMessage());
            return false;
        }
    }

    public void releaseResource() {
        SiliconFlowClient.shutdown();
    }

    private static class SiliconFlowClient {
        private final OkHttpClient httpClient;
        private final ObjectMapper objectMapper;
        private static final String TAG = "SiliconFlowClient";
        // 单线程池（用于执行同步网络请求）
        private static final ExecutorService executor = Executors.newSingleThreadExecutor();

        public SiliconFlowClient() {
            this.httpClient = new OkHttpClient.Builder()
                    .connectTimeout(10, TimeUnit.SECONDS)  // 连接超时（对应 HttpClient 的 connectTimeout）
                    .readTimeout(10, TimeUnit.SECONDS)     // 读取超时（对应 HttpRequest 的 timeout）
                    .writeTimeout(10, TimeUnit.SECONDS)    // 写入超时
                    .build();
            this.objectMapper = new ObjectMapper();
        }

        public String sendRequest(String image1Base64, String image2Base64, String prompt) throws ExecutionException, InterruptedException {
            // 1. 使用Callable在子线程执行同步请求
            Callable<String> requestTask = () -> {
                try {
                    System.out.println("[API] Building request body...");
                    ObjectNode requestBody = buildRequestBody(image1Base64, image2Base64, prompt);
                    String jsonBody = objectMapper.writeValueAsString(requestBody);
                    System.out.println("[API] Request JSON length: " + jsonBody.length() + " chars");

                    System.out.println("[API] Preparing HTTP request...");
                    System.out.println("[API] URL: " + API_URL);
                    System.out.println("[API] Model: " + MODEL_NAME);

                    RequestBody body = RequestBody.create(jsonBody, MediaType.parse("application/json; charset=utf-8"));
                    Request request = new Request.Builder()
                            .url(API_URL)
                            .addHeader("Content-Type", "application/json")
                            .addHeader("Authorization", "Bearer " + API_KEY)
                            .post(body)
                            .build();

                    System.out.println("[API] Sending HTTP request..." + request.headers().toString());

                    try(Response response = this.httpClient.newCall(request).execute()) {
                        if (!response.isSuccessful()) {
                            System.err.println("[API] Error response: " + response.body());
                            throw new IOException("API request failed with status: " + response.code());
                        }
                        return response.body().string();
                    } catch (IOException e) {
                        System.err.println("[API]IO Exception");
                        e.printStackTrace();
                        throw new IOException("failed to send request");
                    }
                } catch (Exception e) {
                    System.err.println("[API]Exception");
                    e.printStackTrace();
                    throw new IOException("failed to send request");
                }
            };

            // 2. 提交任务到线程池并阻塞等待结果
            Future<String> future = executor.submit(requestTask);
            return future.get(); // 阻塞等待子线程执行完毕并返回结果
        }

        private ObjectNode buildRequestBody(String image1Base64, String image2Base64, String prompt) {
            System.out.println("[API] Building request payload...");

            ObjectNode root = objectMapper.createObjectNode();
            root.put("model", MODEL_NAME);

            ArrayNode messages = objectMapper.createArrayNode();
            ObjectNode message = objectMapper.createObjectNode();
            message.put("role", "user");

            ArrayNode content = objectMapper.createArrayNode();

            // 添加文本提示
            ObjectNode textContent = objectMapper.createObjectNode();
            textContent.put("type", "text");
            textContent.put("text", prompt);
            content.add(textContent);

            // 添加图片
            ObjectNode image1Content = objectMapper.createObjectNode();
            image1Content.put("type", "image_url");
            ObjectNode image1Url = objectMapper.createObjectNode();
            image1Url.put("url", "data:image/png;base64," + image1Base64);
            image1Content.set("image_url", image1Url);
            content.add(image1Content);

            ObjectNode image2Content = objectMapper.createObjectNode();
            image2Content.put("type", "image_url");
            ObjectNode image2Url = objectMapper.createObjectNode();
            image2Url.put("url", "data:image/png;base64," + image1Base64);
            image2Content.set("image_url", image2Url);
            content.add(image2Content);

            message.set("content", content);
            messages.add(message);
            root.set("messages", messages);

            root.put("max_tokens", 100);
            root.put("temperature", 0.1);

            System.out.println("[API] Request body built successfully");
            return root;
        }

        /**
         * 释放资源（如退出应用时调用）
         */
        public static void shutdown() {
            executor.shutdown();
        }
    }
}